﻿namespace EasyToolkit.BindingTemplates.Convertors
{
    using System;
    using EasyToolkit.BindingTemplates.Context;
    using EasyToolkit.BindingTemplates.Definitions.Binding;

    static class SpecificConvertors
    {
        public static void TryConvert(IBindingDefinition bindingDefinition, ref object data)
        {
            if (! bindingDefinition.BindingType.Equals(data.GetType()))
            {
                if (bindingDefinition.BindingType == typeof(System.DateTime) || (bindingDefinition.BindingTypeIsGeneric && bindingDefinition.BindingGenericType == typeof(DateTime)))
                    data = ToDateTime(bindingDefinition.BindingType, data);
                else if (bindingDefinition.BindingType == typeof(bool) || (bindingDefinition.BindingTypeIsGeneric && bindingDefinition.BindingGenericType == typeof(bool)))
                    data = ToBoolean(bindingDefinition.BindingType, data);
                else
                {
                    if (! bindingDefinition.BindingTypeIsGeneric)
                        data = Convert.ChangeType(data, bindingDefinition.BindingType);
                    else if(bindingDefinition.BindingGenericTypeDefinition.GetGenericTypeDefinition() != typeof(Nullable<>))
                        data = Convert.ChangeType(data, bindingDefinition.BindingType);
                }
            }
        }

        private static object ToDateTime(Type type, object obj)
        {
            object ret = null;
            if (obj != null)
            {
                if (obj is DateTime)
                    ret = obj;
                else
                {
                    if (obj is double)
                        ret = DateTime.FromOADate((double)obj);
                    else if (obj is string)
                    {
                        DateTime date;
                        if (DateTime.TryParse(obj as string, out date))
                            ret = date;
                    }
                    else
                        ret = Convert.ChangeType(obj, type);
                }
            }
            return ret;
        }

        private static object ToBoolean(Type type, object obj)
        {
            object ret = null;
            if (obj != null)
            {
                if (obj is bool)
                    ret = obj;
                else
                {
                    string objAsString;
                    if (obj is string)
                        objAsString = (obj as string);
                    else
                        objAsString = obj.ToString();

                    bool b;
                    if (bool.TryParse(objAsString, out b))
                        ret = b;
                    else
                    {
                        objAsString = objAsString.Trim().ToUpper();
                        if (objAsString.Equals("T") || objAsString.Equals("1"))
                            ret = true;
                        else if (objAsString.Equals("F") || objAsString.Equals("0"))
                            ret = false;
                    }
                }
            }
            return ret;            
        }
    }
}
